package com.onLineCar.vehicle.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.onLineCar.common.core.domain.Result;
import com.onLineCar.common.core.utils.StringUtils;
import com.onLineCar.common.redis.service.RedisService;
import com.onLineCar.common.security.service.TokenService;
import com.onLineCar.driver.domain.entity.TDriver;
import com.onLineCar.openFeign.DriverFeign;
import com.onLineCar.openFeign.ManageRPCFeign;
import com.onLineCar.openFeign.MessageFeign;
import com.onLineCar.vehicle.config.RateLimiter;
import com.onLineCar.vehicle.config.SnowflakeIdGenerator;
import com.onLineCar.vehicle.entity.TblOrder;
import com.onLineCar.vehicle.entity.request.*;
import com.onLineCar.vehicle.entity.request.driver.DriverOrderRequest;
import com.onLineCar.vehicle.entity.request.message.MessageRequest;
import com.onLineCar.vehicle.entity.request.user.UserOrderRequest;
import com.onLineCar.vehicle.mapper.TblOrderMapper;
import com.onLineCar.vehicle.orderEnum.OrderStatusEnum;
import com.onLineCar.vehicle.service.ITblOrderService;
import lombok.extern.log4j.Log4j2;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static com.onLineCar.vehicle.config.FinalStatus.IS_DISSENT;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author Xinke_Li
 * @since 2023-12-11
 */
@Service
@Log4j2
public class TblOrderServiceImpl extends ServiceImpl<TblOrderMapper, TblOrder> implements ITblOrderService {
    private final MessageFeign messageFeign;

    private final RedisService redisService;

    private final TblOrderMapper tblOrderMapper;

    private final ManageRPCFeign manageRPCFeign;

    private final RedissonClient redissonClient;

    private final DriverFeign driverFeign;

    private final RateLimiter rateLimiter;

    public String orderNumber = "";
    @Autowired
    private TokenService tokenService;

    public final  Integer one = 1;
    public TblOrderServiceImpl(RedisService redisService, TblOrderMapper tblOrderMapper, @Qualifier("com.onLineCar.openFeign.ManageRPCFeign") ManageRPCFeign manageRPCFeign, RedissonClient redissonClient, @Qualifier("com.onLineCar.openFeign.DriverFeign") DriverFeign driverFeign, @Qualifier("com.onLineCar.openFeign.MessageFeign") MessageFeign messageFeign) {
        //使用传入的参数初始化rateLimiter对象，限制订单的提交速率。
        rateLimiter = new RateLimiter(10, 100);
        this.redisService = redisService;
        this.tblOrderMapper = tblOrderMapper;
        this.manageRPCFeign = manageRPCFeign;
        this.redissonClient = redissonClient;
        this.driverFeign = driverFeign;
        this.messageFeign = messageFeign;
    }

    /**
     * @description: 生成订单编号
     * @author: Lxk
     * @date: 2023/12/23 9:54
     * @param: []
     * @return: java.lang.String
     **/
    @Override
    public String createAnOrderNumber() {
        // 调用雪花算法工具类生成订单编号
        String orderId = String.valueOf(new SnowflakeIdGenerator(1, 1).nextId());

        redisService.redisTemplate.opsForSet().add("orderId",orderId);

        redisService.redisTemplate.expire("orderId", 180, TimeUnit.SECONDS); // 设置过期时间为180秒

        return orderId;
    }




    /**
     * @description: 用户下单
     * @author: Lxk
     * @date: 2023/12/12 10:50
     * @param: [tblOrder]
     * @return: int
     **/
    @Override
    public String placeAnOrder(TblOrder tblOrder) {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        Runnable request = () -> {
            // 处理订单请求的业务逻辑
            Set<Object> orderIds = redisService.redisTemplate.opsForSet().members("orderId");
            boolean contains = orderIds.contains(tblOrder.getOrderNumber());
            if (!contains){
                throw new RuntimeException("订单已处理");
            }
            redisService.redisTemplate.opsForSet().remove("orderId",tblOrder.getOrderNumber());

            tblOrder.setStartTime(new Date());
            int insert = tblOrderMapper.insert(tblOrder);
            if (0 == insert){
                throw new RuntimeException("订单提交失败!");
            }
            orderNumber = tblOrder.getOrderNumber();
            System.out.println("Processing order " + tblOrder.getOrderNumber());
            countDownLatch.countDown();
        };
        rateLimiter.submitRequest(request);
        try {
            countDownLatch.await();
            return orderNumber;
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * @description: redisson分布式锁接单
     * @author: Lxk
     * @date: 2023/12/23 11:20
     * @param: [reqDriverPreemptOrder]
     * @return: boolean
     **/
    @Override
    public boolean redissonDriverPreempt(ReqDriverPreemptOrder reqDriverPreemptOrder) {
        String lockKey = "order_lock_" + reqDriverPreemptOrder.getOrderNumber();
        RLock lock = redissonClient.getLock(lockKey);
        try {
            lock.lock(); // 获取锁
            // 尝试获取锁，等待时间为3秒，持有锁的时间为5秒
            if (lock.tryLock(3, 5, TimeUnit.SECONDS)) {
                // 获取到锁，执行抢单逻辑
                String orderNumber = reqDriverPreemptOrder.getOrderNumber();

                if (StringUtils.isNotBlank(orderNumber)) {
                    LambdaUpdateWrapper<TblOrder> updateWrapper = new LambdaUpdateWrapper<>();

                    // 创建查询条件
                    updateWrapper.eq(TblOrder::getOrderNumber, orderNumber);

                    // 设置需要修改的字段值
                    updateWrapper.set(TblOrder::getDriverId, reqDriverPreemptOrder.getDriverId());
                    Result<TDriver> tDriverResult = driverFeign.queryDriverListByDriverId(reqDriverPreemptOrder.getDriverId());
                    TDriver tDriver = tDriverResult.getData();

                    updateWrapper.set(TblOrder::getDriverPhone, tDriver.getDriverTell());
                    //获取车辆ID
                    Integer carId = tDriver.getCarId();
                    //远程调用查看车辆信息
                    List<ApiVehicleInfoDto> data = manageRPCFeign.queryVehicleInfoByVehicleIds(Collections.singletonList(carId)).getData();

                    String plateNumber = data.get(0).getPlateNumber();

                    updateWrapper.set(TblOrder::getPlateNumber, plateNumber);

                    updateWrapper.set(TblOrder::getStatus, OrderStatusEnum.ORDER_STATUS_DRIVER.getOrderCode());

                    updateWrapper.set(TblOrder::getDriverGrabTime, new Date());

                    //远程调用发邮件
                    MessageRequest messageRequest = new MessageRequest();
                    messageRequest.setTag("driverTakeOrder");
                    messageRequest.setOrderNumber(reqDriverPreemptOrder.getOrderNumber());
                    messageFeign.shortMessage(messageRequest);

                    tblOrderMapper.update(null, updateWrapper);
                }
                lock.unlock();
                return true;
            } else {
                // 未获取到锁，抢单失败
                return false;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        } finally {
            lock.unlock();
        }
    }

    /**
     * @description: 用户取消订单
     * @author: Lxk
     * @date: 2023/12/25 17:09
     * @param: [reconciliation]
     * @return: int
     **/
    @Override
    public int cancelOrder(Reconciliation reconciliation) {
        TblOrder tblOrder = this.selectOrderNumber(reconciliation.getOrderNumber());
        if (ObjectUtils.isEmpty(tblOrder)) {
            // 订单不存在
            throw new RuntimeException("订单不存在");
        }

        LambdaUpdateWrapper<TblOrder> tblOrderLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        //if (tblOrder.getStatus().equals(OrderStatusEnum.ORDER_STATUS_START_POINT.getOrderCode())) {
            // TODO: 司机已到达起点，此时取消订单需支付违规费用5元
            // 取消订单，将订单状态修改为已取消
            //tblOrderLambdaUpdateWrapper.set(TblOrder::getStatus,OrderStatusEnum.ORDER_STATUS_CANCEL.getOrderCode());
            //updateStatus(reconciliation);
        //}
        // 取消订单，将订单状态修改为已取消
        tblOrderLambdaUpdateWrapper.set(TblOrder::getStatus,OrderStatusEnum.ORDER_STATUS_CANCEL.getOrderCode());

        return Result.SUCCESS;
    }

    /**
     * @description: 根据用户ID查询订单详情
     * @author: Lxk
     * @date: 2023/12/27 22:32
     * @param: [passengerInfoId]
     * @return: com.onLineCar.vehicle.entity.TblOrder
     **/
    @Override
    public TblOrder servletByInfoId(Integer passengerInfoId) {
        return tblOrderMapper.selectOne(Wrappers.<TblOrder>lambdaQuery()
                .eq(TblOrder::getPassengerInfoId, passengerInfoId)
                .eq(TblOrder::getDeleteOrNo, one));
    }

    /**
     * @description: 用户查看自己的所有订单
     * @author: Lxk
     * @date: 2023/12/28 14:30
     * @param: [userOrderRequest]
     * @return: java.util.List<com.onLineCar.vehicle.entity.TblOrder>
     **/
    @Override
    public IPage<TblOrder> selectAllByUserId(UserOrderRequest userOrderRequest) {
        Long userid = tokenService.getLoginUser().getUserid();
        LambdaQueryWrapper<TblOrder> queryWrapper = new LambdaQueryWrapper<>();
        Page<TblOrder> tblOrderPage = new Page<>(userOrderRequest.getPageNum(), userOrderRequest.getPageSize());
        if (StringUtils.isNotNull(userid)) {
            queryWrapper.eq(TblOrder::getPassengerInfoId, userid);
        }

        if (StringUtils.isNotBlank(userOrderRequest.getOrderNumber())) {
            queryWrapper.eq(TblOrder::getOrderNumber, userOrderRequest.getOrderNumber());
        }

        if (StringUtils.isNotBlank(userOrderRequest.getDriverPhone())) {
            queryWrapper.eq(TblOrder::getDriverPhone, userOrderRequest.getDriverPhone());
        }

        if (userOrderRequest.getServiceType() != null) {
            queryWrapper.eq(TblOrder::getServiceType, userOrderRequest.getServiceType());
        }



        return tblOrderMapper.selectPage(tblOrderPage, queryWrapper);
    }

    /**
     * @description:  司机查看自己的所有订单
     * @author: Lxk
     * @date: 2023/12/28 16:37
     * @param: [driverOrderRequest]
     * @return: com.baomidou.mybatisplus.core.metadata.IPage<com.onLineCar.vehicle.entity.TblOrder>
     **/
    @Override
    public IPage<TblOrder> selectAllByDriverId(DriverOrderRequest driverOrderRequest) {
        LambdaQueryWrapper<TblOrder> queryWrapper = new LambdaQueryWrapper<>();

        if (StringUtils.isNotBlank(driverOrderRequest.getDriverPhone())) {
            queryWrapper.eq(TblOrder::getDriverPhone, driverOrderRequest.getDriverPhone());
        }

        if (StringUtils.isNotBlank(driverOrderRequest.getOrderNumber())) {
            queryWrapper.eq(TblOrder::getOrderNumber, driverOrderRequest.getOrderNumber());
        }

        if (driverOrderRequest.getServiceType() != null) {
            queryWrapper.eq(TblOrder::getServiceType, driverOrderRequest.getServiceType());
        }

        Page<TblOrder> tblOrderPage = new Page<>(driverOrderRequest.getPageNum(), driverOrderRequest.getPageSize());

        return tblOrderMapper.selectPage(tblOrderPage, queryWrapper);
    }

    @Override
    public List<TblOrder> selectOrderByDriverId(Integer driverId) {
        return tblOrderMapper.selectOrderByDriverId(driverId);
    }

    /**
     * @description: 根据订单号修改状态
     * @author: Lxk
     * @date: 2023/12/30 10:52
     * @param: [orderNumber]
     * @return: java.lang.String
     **/
    @Override
    public String updateUserReach(RequestUpdate requestUpdate) {
        LambdaUpdateWrapper<TblOrder> updateWrapper = new LambdaUpdateWrapper<>();

        // 创建查询条件
        updateWrapper.eq(TblOrder::getOrderNumber, requestUpdate.getOrderNumber());

        if(requestUpdate.getDriverStatus()==3){
            updateWrapper.set(TblOrder::getReceivePassengerTime, new Date());
        }

        if(requestUpdate.getDriverStatus()==4){
            updateWrapper.set(TblOrder::getPassengerGetoffTime, new Date());
        }

        // 设置需要修改的字段值
        updateWrapper.set(TblOrder::getStatus,requestUpdate.getDriverStatus());

        updateWrapper.set(TblOrder::getUpdateTime, new Date());

        tblOrderMapper.update(null, updateWrapper);

        return "Orders updated successfully";
    }


    /**
     * @description: 司机接单
     * @author: Lxk
     * @date: 2023/12/18 8:50
     * @param: [tblOrder]
     * @return: int
     **/
    @Override
    public int driverTakeOrder(TblOrder tblOrder) {
        String orderNumber = tblOrder.getOrderNumber();

        if (StringUtils.isNotBlank(orderNumber)) {
            LambdaUpdateWrapper<TblOrder> updateWrapper = new LambdaUpdateWrapper<>();

            // 创建查询条件
            updateWrapper.eq(TblOrder::getOrderNumber, orderNumber);

            // 设置需要修改的字段值
            updateWrapper.set(TblOrder::getDriverId, tblOrder.getDriverId());

            updateWrapper.set(TblOrder::getDriverPhone, tblOrder.getDriverPhone());

            updateWrapper.set(TblOrder::getStatus, OrderStatusEnum.ORDER_STATUS_DRIVER.getOrderCode());

            updateWrapper.set(TblOrder::getDriverGrabTime, new Date());

            int result = tblOrderMapper.update(null, updateWrapper);

            if (0 == result) {
                return Result.error().getCode();
            }
        }
        return 1;
    }

    /**
     * @description: 根据訂單狀態查询订单
     * @author: Lxk
     * @date: 2023/12/18 17:28
     * @param: [status]
     * @return: java.util.List<com.onLineCar.vehicle.entity.TblOrder>
     **/
    @Override
    public List<TblOrder> selectList() {
        LambdaQueryWrapper<TblOrder> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(TblOrder::getStatus, OrderStatusEnum.ORDER_STATUS_START.getOrderCode());

        return tblOrderMapper.selectList(queryWrapper);
    }

    /**
     * @description: 订单列表
     * @author: Lxk
     * @date: 2023/12/12 10:32
     * @param: [tblOrderRequest]
     * @return: java.util.List<com.onLine.vehicle.entity.TblOrder>
     **/
    @Override
    public IPage<TblOrder> selectOrder(TblOrderRequest tblOrderRequest) {
        LambdaQueryWrapper<TblOrder> queryWrapper = new LambdaQueryWrapper<>();

        if (StringUtils.isNotBlank(tblOrderRequest.getOrderNumber())) {
            queryWrapper.eq(TblOrder::getOrderNumber, tblOrderRequest.getOrderNumber());
        }

        if (StringUtils.isNotBlank(tblOrderRequest.getPlateNumber())) {
            queryWrapper.eq(TblOrder::getPlateNumber, tblOrderRequest.getPlateNumber());
        }

        if (StringUtils.isNotBlank(tblOrderRequest.getPassengerPhone())) {
            queryWrapper.eq(TblOrder::getPassengerPhone, tblOrderRequest.getPassengerPhone());
        }

        if (StringUtils.isNotBlank(tblOrderRequest.getDriverPhone())) {
            queryWrapper.eq(TblOrder::getDriverPhone, tblOrderRequest.getDriverPhone());
        }

        if (tblOrderRequest.getStatus() != null) {
            queryWrapper.eq(TblOrder::getStatus, tblOrderRequest.getStatus());
        }

        if (tblOrderRequest.getPayType() != null) {
            queryWrapper.eq(TblOrder::getPayType, tblOrderRequest.getPayType());
        }

        if (tblOrderRequest.getStartTime() != null) {
            queryWrapper.ge(TblOrder::getStartTime, tblOrderRequest.getStartTime());
        }

        if (tblOrderRequest.getCreateTime() != null) {
            queryWrapper.le(TblOrder::getCreateTime, tblOrderRequest.getCreateTime());
        }

        Page<TblOrder> tblOrderPage = new Page<>(tblOrderRequest.getPageNum(), tblOrderRequest.getPageSize());

        return tblOrderMapper.selectPage(tblOrderPage, queryWrapper);
        }

    /**
     * @description: 查看订单详情
     * @author: Lxk
     * @date: 2023/12/13 18:55
     * @param: [orderNumber]
     * @return: com.onLine.vehicle.entity.TblOrder
     **/
    @Override
    public TblOrder selectOrderNumber(String orderNumber) {
        return tblOrderMapper.selectOne(new LambdaQueryWrapper<TblOrder>()
                .eq(TblOrder::getOrderNumber, orderNumber));
    }

    /**
     * @description: 删除订单
     * @author: Lxk
     * @date: 2023/12/13 20:06
     * @param: [orderNumber]
     * @return: int
     **/
    @Override
    public int deleteOrderNumber(String orderNumber) {
        return tblOrderMapper.delete(new LambdaQueryWrapper<TblOrder>()
                .eq(TblOrder::getOrderNumber, orderNumber));
    }

    /**
     * @description: 根据城市查询订单
     * @author: Lxk
     * @date: 2023/12/14 20:41
     * @param: [cityCode]
     * @return: java.util.List<com.onLine.vehicle.entity.TblOrder>
     **/
    @Override
    public List<TblOrder> selectByCityCode(Long cityCode) {
        return tblOrderMapper.selectList(new LambdaQueryWrapper<TblOrder>()
                .eq(TblOrder::getStatus, OrderStatusEnum.ORDER_STATUS_START.getOrderCode())
                .eq(TblOrder::getCityCode, cityCode));
    }

    /**
     * @description: 根据用户id查询订单
     * @author: Lxk
     * @date: 2023/12/15 15:41
     * @param: [id]
     * @return: com.onLine.vehicle.entity.TblOrder
     **/
    @Override
    public TblOrder selectByUserId(Long id) {
        QueryWrapper<TblOrder> tblOrderLambdaQueryWrapper = new QueryWrapper<>();
        tblOrderLambdaQueryWrapper.eq("status", OrderStatusEnum.ORDER_STATUS_START.getOrderCode());
        tblOrderLambdaQueryWrapper.eq("passenger_info_id", id);
        return tblOrderMapper.selectOne(tblOrderLambdaQueryWrapper);
    }

    /**
     * @description: 根据司机id查询订单
     * @author: Lxk
     * @date: 2023/12/15 16:06
     * @param: [driverId]
     * @return: java.util.List<com.onLine.vehicle.entity.TblOrder>
     **/
    @Override
    public TblOrder selectByDriverId(Integer driverId) {
        return tblOrderMapper.selectOne(Wrappers.<TblOrder>lambdaQuery()
                .eq(TblOrder::getDriverId, driverId)
                .eq(TblOrder::getStatus, OrderStatusEnum.ORDER_STATUS_DRIVER.getOrderCode())
        );
    }

    /**
     * @description: 查询所有的已结束订单以及已取消订单
     * @author: Lxk
     * @date: 2023/12/18 18:43
     * @param: []
     * @return: java.util.List<com.onLineCar.vehicle.entity.TblOrder>
     **/
    @Override
    public List<TblOrder> selectAllCloseOrder() {
        LambdaQueryWrapper<TblOrder> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.in(TblOrder::getStatus, OrderStatusEnum.ORDER_STATUS_PAY_SUCCESS.getOrderCode(),
                OrderStatusEnum.ORDER_STATUS_CANCEL.getOrderCode());

        return tblOrderMapper.selectList(queryWrapper);
    }

    @Override
    public void updateOrderStateByOrderNumber(RequestUpdate requestUpdate) {
        tblOrderMapper.updateOrderStateByOrderNumber(requestUpdate);
    }

    /**
     * @description: 用户下单2,分库分表
     * @author: Lxk
     * @date: 2023/12/21 14:44
     * @param: [tblOrder]
     * @return: java.lang.String
     **/
    @Override
    public String userPlacesAnOrder(TblOrder tblOrder) {
        // 调用雪花算法工具类生成订单编号
        long orderId = new SnowflakeIdGenerator(1, 1).nextId();

        // 给订单号赋值
        tblOrder.setOrderNumber(String.valueOf(orderId));
        tblOrder.setStartTime(new Date());

        tblOrderMapper.insert(tblOrder);
        String orderNumber = tblOrder.getOrderNumber();
        System.out.println(orderNumber);

        return orderNumber;
    }

    @Override
    public TblOrder selectOrderByOrderNumber(String orderNumber) {
        return tblOrderMapper.selectOne(new LambdaQueryWrapper<TblOrder>()
                .eq(TblOrder::getOrderNumber, orderNumber));
    }

    /**
     * @description: 修改订单方法
     * @author: Lxk
     * @date: 2023/12/25 19:23
     * @param: [reconciliation]
     **/
    public void updateStatus(Reconciliation reconciliation) {
        LambdaUpdateWrapper<TblOrder> updateWrapper = new LambdaUpdateWrapper<>();

        updateWrapper.eq(TblOrder::getPassengerInfoId, reconciliation.getPassengerInfoId())
                .eq(TblOrder::getOrderNumber, reconciliation.getOrderNumber())
                .set(TblOrder::getIsCancel, IS_DISSENT);

        tblOrderMapper.update(null, updateWrapper);

        tblOrderMapper.update(null, updateWrapper);
    }

    /**
     * @description: 疑义账单
     * @author: Lxk
     * @date: 2023/12/25 14:12
     * @param: [reconciliation]
     * @return: void
     **/
    @Override
    public int updatebill(Reconciliation reconciliation) {
        LambdaUpdateWrapper<TblOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(TblOrder::getPassengerInfoId, reconciliation.getPassengerInfoId())
                .eq(TblOrder::getOrderNumber, reconciliation.getOrderNumber())
                .set(TblOrder::getIsDissent, IS_DISSENT);

        tblOrderMapper.update(null, updateWrapper);
        return Result.SUCCESS;
    }

}
